<!-- 不需要尺寸定位，直接撑大到父容器，父容器需要相对定位 -->
<template>
  <div class="scrollXV3" ref="scrollBoxDom" :style="{
                          '--scrollWidthX':  scrollD.widthX, // 滚动条宽带
                          '--scrollWidthY':  scrollD.widthY, // 滚动条宽带

                          '--paddingX': scrollD.paddingX,  // 滚动条边距
                          '--paddingY': scrollD.paddingY,  // 滚动条边距

                          '--showX': scrollD.showX, // 不写或true为显示X滚动条
                          '--showY': scrollD.showY, // 显示Y滚动条

                          '--scrollColorX': scrollD.colorX, // 滚动条颜色
                          '--scrollColorY': scrollD.colorY, // 滚动条颜色

                          '--scrolloX': scrollD.opacityX, // 滚动条透明度
                          '--scrolloY': scrollD.opacityY, // 滚动条透明度
                      }">
    <el-scrollbar class="scrollXV3Box" v-bind="$attrs"
                  :always="scrollD.always"
                  :height="heightD" :max-height="maxHeight">
      <slot/>
    </el-scrollbar>
  </div>
</template>

<script setup>
import {ref, computed, onMounted, onUnmounted,nextTick,onBeforeMount} from 'vue'
import {ElScrollbar} from 'element-plus'

const props = defineProps({
  // 滚动条设置
  scrollStyle: {
    type: Object,
    default: {
      width: '10px',      // 全部滚动条宽度。接受Number或string
      widthX: '10px',     // 横向滚动条宽度（优先级大与width）。接受Number或string
      widthY: '10px',     // 纵向向滚动条宽度（优先级大与width）。接受Number或string
      padding: '2px',         // 滚动条边距。
      paddingX: '2px',        // 横向滚动条边距。
      paddingY: '2px',        // 纵向滚动条边距。
      color: '#909399',   // 全部滚动条颜色
      colorX: '#909399',  // 横向滚动条颜色（优先级大与color）
      colorY: '#909399',  // 纵向滚动条颜色（优先级大与color）
      opacity: 0.7,       // 滚动条透明度
      opacityX: 0.7,      // 横向滚动条透明度（优先级大与opacity）
      opacityY: 0.7,      // 纵向滚动条透明度（优先级大与opacity）
      show: true,         // 全部滚动条显示隐藏。
      showX: true,        // 不写或true为显示X滚动条，否则隐藏（优先级大与show）
      showY: true,        // 显示Y轴（优先级大与show）
      always: false       // 可以显示滚动条时，总是显示滚动条
    }
  },

  // 打开时位置
  positionX: {
    type: Number,
    default: 0
  },

  positionY: {
    type: Number,
    default: 0
  },

  // 滚动条组件的内容区域的高度
  height: {
    type: [String, Number],
    default: '100%'
  },

  maxHeight: {
    type: [String, Number],
    default: '100%'
  },

  // 是否采用监听窗口变化改变高度（一般使用父级绝对布局使用100%高度，但绝对布局方式使菜单的收缩时动画不流畅）
  onHeight: {
    type: [String, Number],
    default: undefined
  },
})


// region 工具函数
// 判断prop传参的值。接受[String,Number]的style样式尺寸
function getPx(text, defaultPx = 'px') {
  let tempList = ['px', 'rpx', 'vw', 'vh', '%', 'em', 'auto']
  if (typeof text == 'string') {
    const havePx = tempList.find(row => text.includes(row))
    if (havePx) {
      return text
    } else {
      return `${parseFloat(text)}${defaultPx}`
    }
  } else if (typeof text == 'number') {
    let temp = parseFloat(text)
    return `${temp}${defaultPx}`
  }
  return text
}

// endregion


// region 滚动条样式
const scrollD = computed(() => {
  function __setWidth(widthObj) {
    let width = '10px'
    if (widthObj != undefined) {
      // 接受Number或string
      if (typeof widthObj == 'string') {
        width = widthObj
      } else {
        width = String(widthObj) + 'px'
      }
    }
    return width
  }

  // 设置全部宽度
  let widthX = __setWidth(props.scrollStyle.width)
  let widthY = widthX
  // 设置单条宽
  if (props.scrollStyle.widthX != undefined) {
    widthX = __setWidth(props.scrollStyle.widthX)
  }
  if (props.scrollStyle.widthY != undefined) {
    widthY = __setWidth(props.scrollStyle.widthY)
  }

  // 设置颜色
  let colorX = props.scrollStyle.color || '#87888A'
  let colorY = colorX
  if (props.scrollStyle.colorX != undefined) {
    colorX = props.scrollStyle.colorX
  }
  if (props.scrollStyle.colorY != undefined) {
    colorY = props.scrollStyle.colorY
  }

  // 设置显示或隐藏
  let showX = (props.scrollStyle.show != undefined && Boolean(props.scrollStyle.show) == false) ? 'none' : 'block'
  let showY = showX
  if (props.scrollStyle.showX != undefined) {
    showX = (props.scrollStyle.showX != undefined && Boolean(props.scrollStyle.showX) == false) ? 'none' : 'block'
  }
  if (props.scrollStyle.showY != undefined) {
    showY = (props.scrollStyle.showY != undefined && Boolean(props.scrollStyle.showY) == false) ? 'none' : 'block'
  }


  // 设置透明度
  let opacityX = props.scrollStyle.opacity || 0.7
  let opacityY = opacityX
  if (props.scrollStyle.opacityX != undefined) {
    opacityX = props.scrollStyle.opacityX
  }
  if (props.scrollStyle.opacityY != undefined) {
    opacityY = props.scrollStyle.opacityY
  }

  // 设置边距
  function __setPadding(topObj) {
    let padding = '2px'
    if (topObj != undefined) {
      // 接受Number或string
      if (typeof topObj == 'string') {
        padding = topObj
      } else {
        padding = String(topObj) + 'px'
      }
    }
    return padding
  }

  let paddingX = __setPadding(props.scrollStyle.padding)
  let paddingY = paddingX
  if (props.scrollStyle.paddingX != undefined) {
    paddingX = __setPadding(props.scrollStyle.paddingX)
  }
  if (props.scrollStyle.paddingY != undefined) {
    paddingY = __setPadding(props.scrollStyle.paddingY)
  }

  return {
    widthX,
    widthY,
    colorX,
    colorY,
    showX,
    showY,
    opacityX,
    opacityY,
    paddingX,
    paddingY,
    always: props.scrollStyle.always != undefined ? Boolean(props.scrollStyle.always) : false
  }
})
// endregion


// region 事件

// 设置定边
const setTop = (value) => {
  scrollDom.value.setScrollTop(value)
}
// 设置左边
const setLeft = (value) => {
  scrollDom.value.setScrollLeft(value)
}


// endregion




// region 高度
const scrollBoxDom = ref({})
const calcHW = () => {
  const hValue = window.innerHeight - (scrollBoxDom.value?.offsetTop || 0) - Number.parseFloat(props.onHeight)
  heightD.value = getPx(hValue)
  maxHeight.value = getPx(props.maxHeight)
}

const heightD = ref(0)

const maxHeight = ref(0)

onMounted(() => {
  if (props.onHeight == undefined){
    heightD.value = getPx(props.height)
    maxHeight.value = getPx(props.maxHeight)
  }else{
    window.addEventListener('resize', calcHW)
    calcHW()
    setTimeout(() => {
      nextTick(() => {
        calcHW()
      })
    }, 200)
  }
})

onUnmounted(() => {
  if (props.onHeight != undefined){
    window.removeEventListener('resize', calcHW)
  }
})

// endregion

defineExpose({
  setTop,
  setLeft
})

</script>

<style scoped lang='scss'>
.scrollXV3 {
  width: 100%;
  height: 100%;

  .scrollXV3Box {
    //height: 100%;
    width: 100%;
  }
}

// 滚动条样式
@mixin scrollStyle() {

  // 横向滚动条
  // 横向滚动条宽度
  $scrollWX: var(--scrollWidthX);
  .is-horizontal {
    //bottom: $scrollWX;
    height: $scrollWX;
    bottom: var(--paddingX);

    .el-scrollbar__thumb {
      height: $scrollWX !important;
      background-color: var(--scrollColorX) !important;
      opacity: var(--scrolloX) !important;
      display: var(--showX);
    }
  }

  // 纵向滚动条
  $scrollWY: var(--scrollWidthY);
  .is-vertical {
    //right: $scrollWY - 4;
    width: $scrollWY;
    right: var(--paddingY);

    .el-scrollbar__thumb {
      width: $scrollWY !important;
      background-color: var(--scrollColorY) !important;
      opacity: var(--scrolloY) !important;
      display: var(--showY);
    }
  }
}


:deep(.scrollXV3Box) {
  @include scrollStyle;
}
</style>